package wifiadm

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"strconv"
	"sync"
	"time"

	"yundian/internel/app/dao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/logic"
	"yundian/internel/app/models/devices"
	"yundian/internel/app/models/devploys"
	"yundian/internel/app/models/devrule"
	"yundian/internel/app/models/devtype"
	"yundian/internel/app/models/placemodel/places"
	"yundian/internel/app/models/ploys"
	"yundian/internel/app/models/prices"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/dingo"
	. "yundian/internel/pkg/dingo/result"
	"yundian/internel/pkg/utils"
)

// ------- 设备相关API请求处理 deviceHandler -------

var wg sync.WaitGroup

// SetStewardDevice 设备绑定
func SetStewardDevice(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.SetStewardDeviceReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId

	if data := dao.NewDeviceDao().SetStewardDevice(param); data.Err != nil {
		Response(ctx)(data.Err.Error(), CodeInternalServerError, false)(OK)
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

func FetchStewardDeviceList(ctx *gin.Context) {
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	dingo.ErrorIf(err).Unwrap()

	param := &request.StewardDeviceListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.LoginUserId = loginUserId
	param.IsAdmin, _ = helper.GetIsAdminFromCtx(ctx)
	param.ParentId, _ = helper.GetParentIdFromCtx(ctx)

	data := dao.NewDeviceDao().FetchStewardDeviceList(param)
	lists := data.Unwrap().([]*request.StewardDeviceListRes)

	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

func FetchDeviceList(ctx *gin.Context) {
	// 请求参数处理
	param := &request.DeviceListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	isAdmin, _ := helper.GetIsAdminFromCtx(ctx)      // 从上下文中获取用户是否为管理员
	parentId, _ := helper.GetParentIdFromCtx(ctx)    // 从上下文中获取当前登录用户的上级ID
	IsPlace, _ := helper.GetIsPlaceFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	param.IsPlace = IsPlace
	param.LoginUserId = loginUserId // 当前登录用户ID
	param.IsAdmin = isAdmin         //角色类型 1:管理员 2:运营商 3:代理、商户 4:员工  5:合伙人

	if helper.IsAdminAndStaff(isAdmin, parentId) {
		param.IsAdmin = helper.TypeNumIsAdminOperator
		param.LoginUserId = 2
	}

	// 获取数据
	data := dao.NewDeviceDao().FetchDeviceListWithType(param)
	lists := data.Unwrap().([]*devices.DeviceType)

	// 响应请求
	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

func FetchDeviceListByUid(ctx *gin.Context) {
	// 请求参数处理
	param := &request.DeviceListReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	isAdmin, _ := helper.GetIsAdminFromCtx(ctx)      // 从上下文中获取用户是否为管理员
	parentId, _ := helper.GetParentIdFromCtx(ctx)    // 从上下文中获取当前登录用户的上级ID
	IsPlace, _ := helper.GetIsPlaceFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	param.IsPlace = IsPlace
	param.LoginUserId = loginUserId // 当前登录用户ID
	param.IsAdmin = isAdmin         //角色类型 1:管理员 2:运营商 3:代理、商户 4:员工  5:合伙人

	if helper.IsAdminAndStaff(isAdmin, parentId) {
		param.IsAdmin = helper.TypeNumIsAdminOperator
		param.LoginUserId = 2
	}

	// 获取数据
	data := dao.NewDeviceDao().FetchDeviceListWithTypeByUid(param)
	lists := data.Unwrap().([]*devices.DeviceType)

	// 响应请求
	Response(ctx)("", CodeSuccess, ResponseList{
		PageNo:     param.PageNo,
		PageSize:   param.PageSize,
		TotalCount: data.Val().(int64),
		TotalPage:  0,
		Data:       lists,
	})(OK)
}

// GetDeviceList 获取设备列表API
func GetDeviceList(ctx *gin.Context) {
	// 请求参数处理
	param := &request.DeviceListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	//log.Print("PageNo：", param.PageNo, "   PageSize:", param.PageSize, "   deviceSn: ", param.DeviceSn)
	data := dao.NewDeviceDao().FetchDeviceListWithType(param)
	// 响应请求
	Response(ctx)("", CodeSuccess,
		ResponseList{
			PageNo:     param.PageNo,
			PageSize:   param.PageSize,
			TotalCount: data.Val().(int64),
			TotalPage:  0,
			Data:       data.Unwrap(),
		},
	)(OK)
}

// GetDeviceListByPage 分页获取设备列表API
func GetDeviceListByPage(ctx *gin.Context) {
	//page,size := helper.GetPageInfo(ctx)
	//Response(ctx)(
	//	"",
	//	CodeSuccess,
	//	getter.DevGetter.GetFromPage(page,size).Unwrap(),
	//)(OK)
}

// GetDeviceBySn 获取设备详情API
func GetDeviceBySn(ctx *gin.Context) {
	param := &struct {
		Sn string `uri:"sn" binding:"required"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindUri(param)).Unwrap()

	//log.Println("kxkxkxkx: ", param.Sn)
	Response(ctx)("", CodeSuccess, dao.NewDeviceDao().FetchDeviceInfoWithType(param.Sn).Unwrap())(OK)
}

// InsertDevice 新增设备信息API
func InsertDevice(ctx *gin.Context) {
	m := devices.New().Mutate(devices.WithCreateAt(dingo.Time(time.Now().Unix())))
	dingo.ErrorIf(ctx.ShouldBindJSON(m)).Unwrap()

	log.Println("InsertDevice： ", m)
	//m.Status = 0 // 0 未启用 1 启用  默认为未启用
	//m.CreateAt = time.Now() // 设备创建时间
	//Response(ctx)("", CodeInsertSuccess,dao.InsertDevice(m).Unwrap())(OK)
}

// BatchInsertDevice 批量新增设备信息API
func BatchInsertDevice(ctx *gin.Context) {
	param := &struct {
		DeviceTypeId int `json:"deviceTypeId" binding:"required"` // 设备类型
		//rule_id int // 设备所属套餐
		Count int `json:"count" binding:"required"` // 生成的条数
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	if err != nil {
		dingo.ErrorIf(err).Unwrap()
	}
	loginUserName, err2 := helper.GetUserNameFromCtx(ctx) // 从上下文中获取用户名
	if err2 != nil {
		dingo.ErrorIf(err2).Unwrap()
	}

	if param.Count > 20000 {
		Response(ctx)("最多只能生成20000条", CodeError, nil)(OK)
		return
	}

	count := param.Count
	var insertCount int
	for i := 0; i < 10; i++ {
		if count >= 2000 {
			count = count - 2000
			insertCount = 2000
		} else {
			insertCount = count
			count = 0
		}

		if insertCount > 0 {
			wg.Add(1)
			go func() {
				defer wg.Done() //减去一个计数
				WaitGroupInsertDevice(param.DeviceTypeId, insertCount, loginUserId, loginUserName)
			}()

			wg.Wait()
		} else {
			break
		}

	}

	//lst := make([]*devices.DeviceModel, 0)
	//
	//// 查询当天最后添加的SN号
	//todaySn := dao.NewDeviceDao().GetDeviceTodaySnByCreateat().Unwrap().(*devices.DeviceModel).DeviceSn
	//sn := 0
	//if todaySn != "" && len(todaySn) > 8 {
	//	// 截取字段串： string:211121YD00237 -> string:00237 -> int:237
	//	sn, _ = strconv.Atoi(todaySn[8:])
	//}
	//
	//deviceTypeInfo := dao.NewDeviceTypeDao().GetDeviceTypeDetail(param.DeviceTypeId).Unwrap().(*devtype.DeviceTypeModel) // 获取设备类型
	//
	//// dev_sn qrcode_url 自动生成
	//for i := 1; i <= param.Count; i++ {
	//	m := devices.New() // .Mutate(devices.WithCreateAt(time.Now().Unix()),devices.WithUpdateAt(time.Now().Unix()))
	//
	//	// 设备类型ID 10:免押密码线 12:套餐密码线
	//	m.DeviceTypeId = param.DeviceTypeId
	//	m.DeviceTypeName = deviceTypeInfo.DeviceName
	//	m.FeeMode = uint8(deviceTypeInfo.FeeMode)
	//	// 密码序号 默认为1
	//	m.PwdIndex = 1
	//	// 密码解锁类型
	//	m.PwdDecodeType = deviceTypeInfo.PwdDecodeType
	//	// 密码解码key
	//	m.PwdSecretKey = deviceTypeInfo.SecretKey
	//	// 共享模式
	//	m.SharedMode = deviceTypeInfo.SharedMode
	//	// 新增设备代理商ID默认为运营商
	//	m.AgentUserId = loginUserId
	//	m.AgentUserName = loginUserName
	//
	//	// 状态
	//	m.State = 1
	//	// 新增时间
	//	m.CreateAt = dingo.Time(time.Now().Unix())
	//	// 更新时间
	//	m.UpdateAt = dingo.Time(time.Now().Unix())
	//
	//	// 设备号累加
	//	sn = sn + 1
	//	// 添加设备批次序列号
	//	m.Sn = sn
	//
	//	//log.Print("当前SN累加为: ",sn)
	//	// 转为String 类型，长度不足5 前面补0
	//	// 例如：390 --> 00390
	//	snStr := strconv.Itoa(sn)
	//	for j := 5 - len(snStr); j > 0; j-- {
	//		//log.Print("snStr的长度: ",len(snStr))
	//		snStr = utils.Join("0", snStr)
	//		//log.Println("snStr的值是：",snStr)
	//
	//	}
	//
	//	//log.Print("当前SN补0为: ",snStr)
	//	today := time.Now().Format("060102")
	//	m.DeviceSn = utils.Join(today, "ZM", snStr)
	//	m.PreSn = utils.Join(today, "ZM") // 批号
	//
	//	//log.Print("当前完整SN为: ", m.DeviceSn)
	//	//m.Tid = data.t_id
	//	//m.Status = 0 // 0 未启用
	//	lst = append(lst, m)
	//	//log.Println("模型内容：", m)
	//
	//	//Response(ctx)("", CodeInsertSuccess,dao.InsertDevice(m).Unwrap())(OK)
	//}

	//log.Println("%V",lst)
	//log.Printf("%v",lst)
	//for i := 0; i < len(lst); i++ {
	//	//log.Println("xxx: ",i)
	//	log.Print("设备整体数据为：",lst[i],"  下标：",i)
	//}
	//Response(ctx)("", CodeSuccess, dao.NewDeviceDao().InsertDevice(lst).Unwrap())(OK)
	//Response(ctx)("", CodeInsertSuccess,dao.GetDeviceTodaySnByCreateat().Unwrap())(OK)
	Response(ctx)("添加成功", CodeSuccess, true)(OK)
}

func WaitGroupInsertDevice(deviceTypeId int, count int, loginUserId int, loginUserName string) {
	lst := make([]*devices.DeviceModel, 0)

	// 查询当天最后添加的SN号
	todaySn := dao.NewDeviceDao().GetDeviceTodaySnByCreateat().Unwrap().(*devices.DeviceModel).DeviceSn
	sn := 0
	if todaySn != "" && len(todaySn) > 8 {
		// 截取字段串： string:211121YD00237 -> string:00237 -> int:237
		sn, _ = strconv.Atoi(todaySn[8:])
	}
	deviceTypeInfo := dao.NewDeviceTypeDao().GetDeviceTypeDetail(deviceTypeId).Unwrap().(*devtype.DeviceTypeModel) // 获取设备类型
	// dev_sn qrcode_url 自动生成
	for i := 1; i <= count; i++ {
		m := devices.New() // .Mutate(devices.WithCreateAt(time.Now().Unix()),devices.WithUpdateAt(time.Now().Unix()))

		// 设备类型ID 10:免押密码线 12:套餐密码线
		m.DeviceTypeId = deviceTypeId
		m.DeviceTypeName = deviceTypeInfo.DeviceName
		m.FeeMode = uint8(deviceTypeInfo.FeeMode)
		// 密码序号 默认为1
		m.PwdIndex = 1
		// 密码解锁类型
		m.PwdDecodeType = deviceTypeInfo.PwdDecodeType
		// 密码解码key
		m.PwdSecretKey = deviceTypeInfo.SecretKey
		// 共享模式
		m.SharedMode = deviceTypeInfo.SharedMode
		// 新增设备代理商ID默认为运营商
		m.AgentUserId = loginUserId
		m.AgentUserName = loginUserName

		// 状态
		m.State = 1
		// 新增时间
		m.CreateAt = dingo.Time(time.Now().Unix())
		// 更新时间
		m.UpdateAt = dingo.Time(time.Now().Unix())

		// 设备号累加
		sn = sn + 1
		// 添加设备批次序列号
		m.Sn = sn

		//log.Print("当前SN累加为: ",sn)
		// 转为String 类型，长度不足5 前面补0
		// 例如：390 --> 00390
		snStr := strconv.Itoa(sn)
		for j := 5 - len(snStr); j > 0; j-- {
			//log.Print("snStr的长度: ",len(snStr))
			snStr = utils.Join("0", snStr)
			//log.Println("snStr的值是：",snStr)

		}

		//log.Print("当前SN补0为: ",snStr)
		today := time.Now().Format("060102")
		m.DeviceSn = utils.Join(today, global.Const.Pre.DevicePre, snStr)
		m.PreSn = utils.Join(today, global.Const.Pre.DevicePre) // 批号

		//log.Print("当前完整SN为: ", m.DeviceSn)
		//m.Tid = data.t_id
		//m.Status = 0 // 0 未启用
		lst = append(lst, m)
		//log.Println("模型内容：", m)
		//Response(ctx)("", CodeInsertSuccess,dao.InsertDevice(m).Unwrap())(OK)
	}
	//log.Println("%V", lst)
	//log.Printf("%v", lst)
	//for i := 0; i < len(lst); i++ {
	//	//log.Println("xxx: ",i)
	//	log.Print("设备整体数据为：", lst[i], "  下标：", i)
	//}

	dao.NewDeviceDao().InsertDevice(lst).Unwrap()

}

// UpdateDeviceBySn 修改设备信息API
func UpdateDeviceBySn(ctx *gin.Context) {
	data := devices.New()
	dingo.ErrorIf(ctx.ShouldBindJSON(data)).Unwrap()
	deviceTypeInfo := dao.NewDeviceTypeDao().GetDeviceTypeDetail(data.DeviceTypeId).Unwrap().(*devtype.DeviceTypeModel) // 获取设备类型
	log.Println("修改设备线", deviceTypeInfo)
	Response(ctx)("", CodeSuccess, dao.NewDeviceDao().UpdateDeviceBySn(data).Unwrap())(OK)
}

// DeleteDeviceBySn 删除设备信息API
func DeleteDeviceBySn(ctx *gin.Context) {
	data := &struct {
		Sn string `json:"deviceSn" binding:"required"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(data)).Unwrap()
	Response(ctx)("", CodeSuccess, dao.NewDeviceDao().DeleteDeviceBySn(data.Sn).Unwrap())(OK)
}

func DeleteDeviceById(ctx *gin.Context) {
	param := &struct {
		Id int `json:"id" binding:"required"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	m := dao.NewDeviceDao().GetDeviceById(param.Id).Unwrap().(*devices.DeviceModel)
	if m.PlaceId > 0 {
		Response(ctx)("已绑定商户，请先解绑商户", CodeSuccess, nil)(OK)
		return
	}
	Response(ctx)("删除成功", CodeSuccess, dao.NewDeviceDao().DeleteDeviceById(param.Id).Unwrap())(OK)
}

func UnBindDevice(ctx *gin.Context) {
	data := &struct {
		Id      int `json:"id" binding:"required"`
		PlaceId int `json:"placeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(data)).Unwrap()

	// 解绑
	dao.NewDeviceDao().UpdateDeviceBindStatus(data.Id).Unwrap()
	// 绑定成功后更新该商户的设备条数 - 包含所有设备类型
	total := dao.NewDeviceDao().GetDeviceCountByPlaceId(data.PlaceId).Unwrap().(int64)
	err := dao.NewPlaceDao().UpdatePlaceCount(data.PlaceId, total)

	Response(ctx)("解绑成功", CodeSuccess, err)(OK)
}

// 获取设备批号
func GetPreDeviceSn(ctx *gin.Context) {

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, err := helper.GetIsAdminFromCtx(ctx) // 从上下文中获取用户是否为管理员
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	parentId, err := helper.GetParentIdFromCtx(ctx) // 从上下文中获取当前登录用户的上级ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	Response(ctx)("", CodeSuccess, dao.NewDeviceDao().GetPreSn(isAdmin, parentId, loginUserId).Unwrap())(OK)
}

// 获取设备序号与条数
func GetSnAndCount(ctx *gin.Context) {
	param := &struct {
		PreSn string `form:"preSn"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	loginUserId, err := helper.GetUserIdFromCtx(ctx) // 获取当前登录用户ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	isAdmin, err := helper.GetIsAdminFromCtx(ctx) // 从上下文中获取用户是否为管理员
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	parentId, err := helper.GetParentIdFromCtx(ctx) // 从上下文中获取当前登录用户的上级ID
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	total := dao.NewDeviceDao().GetDeviceCountByPreSn(param.PreSn, isAdmin, parentId, loginUserId).Unwrap().(int64)
	minDevInfo := dao.NewDeviceDao().GetDeviceMinSnByPreSn(param.PreSn, isAdmin, parentId, loginUserId).Unwrap().(*devices.DeviceModel)
	maxDevInfo := dao.NewDeviceDao().GetDeviceMaxSnByPreSn(param.PreSn, isAdmin, parentId, loginUserId).Unwrap().(*devices.DeviceModel)

	var usedSn []int
	//if maxDevInfo.Sn >= minDevInfo.Sn {
	//	for i := minDevInfo.Sn; i <= maxDevInfo.Sn; i++ {
	//		count := dao.NewDeviceDao().GetDeviceUsedByPreSn(param.PreSn, i).Unwrap().(int64)
	//		if count > 0 {
	//			usedSn = append(usedSn, i)
	//		}
	//	}
	//}

	Response(ctx)("", CodeSuccess, &struct {
		Total  int64 `json:"total"`
		MinSn  int   `json:"minSn"`
		MaxSn  int   `json:"maxSn"`
		UsedSn []int `json:"usedSn"`
	}{
		Total:  total,
		MinSn:  minDevInfo.Sn,
		MaxSn:  maxDevInfo.Sn,
		UsedSn: usedSn,
	})(OK)
}

// 代理商绑定设备
func HandleBindDeviceToAgent(ctx *gin.Context) {
	param := &struct {
		PreSn     string `json:"preSn" binding:"required"` // 批号
		BeginSn   int    `json:"beginSn" binding:"required,gt=0"`
		EndSn     int    `json:"endSn" binding:"required,gt=0"`
		AgentId   int    `json:"agentId" binding:"required,gt=0"`
		AgentName string `json:"agentName"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	// 代理商名称
	userInfo := dao.NewUserDao().GetUserInfoById(param.AgentId).Unwrap().(*users.UserModel)
	param.AgentName = userInfo.Name

	var count int64
	var strs []string
	status := 1
	for i := param.BeginSn; i <= param.EndSn; i++ {
		//deviceSn := utils.Join(param.PreSn, fmt.Sprintf("%0*d", 5, i))
		deviceSn := dao.NewDeviceDao().GetDeviceBySnAndPreSn(param.PreSn, i).Unwrap().(*devices.DeviceModel).DeviceSn
		m := devices.New()
		m.DeviceSn = deviceSn
		m.AgentUserId = param.AgentId
		m.AgentUserName = param.AgentName // 冗余字段 代理商名称
		m.UpdateAt = dingo.Time(time.Now().Unix())

		fmt.Println("AgentName = ", param.AgentName)
		// 判断设备是否已添加
		DevCount := dao.NewDeviceDao().GetDeviceUsedByPreSn(param.PreSn, i).Unwrap().(int64)
		if DevCount <= 0 {
			ok := dao.NewDeviceDao().UpdateDeviceBySn(m).Unwrap().(bool)
			if ok {
				count++
			} else {
				status = 0
				strs = append(strs, deviceSn)
			}
		}
	}
	Response(ctx)(fmt.Sprintf("成功绑定%d条", count), CodeSuccess, &struct {
		Count  int64    `json:"count"`
		Strs   []string `json:"strs"`
		Status int      `json:"status"`
	}{
		Count:  count,
		Strs:   strs,
		Status: status,
	})(OK)
}

// HandleBindDeviceAndRoom 绑定密码线充设备与房间
func HandleBindDeviceAndRoom(ctx *gin.Context) {
	param := &request.BindDeviceAndRoomReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	// 获取设备信息
	deviceInfo := dao.NewDeviceDao().GetDeviceByDeviceSn(param.DeviceSn).Unwrap().(*devices.DeviceModel)
	if deviceInfo.PlaceId != 0 && deviceInfo.PlaceId != param.PlaceId {
		Response(ctx)("设备己绑定其它门店", CodeInvalidParam, false)(OK)
		return
	}
	if param.PlaceName == "" {
		param.PlaceName = deviceInfo.PlaceName
	}

	deviceInfo.State = 2
	deviceInfo.Room = param.Room
	deviceInfo.PlaceId = param.PlaceId
	deviceInfo.DeviceSn = param.DeviceSn
	deviceInfo.PlaceName = param.PlaceName
	deviceInfo.UpdateAt = dingo.Time(time.Now().Unix())
	deviceInfo.DeployAt = dingo.Time(time.Now().Unix())
	if dao.NewDeviceDao().UpdateDeviceBySn(deviceInfo).Err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
		return
	}

	if dao.NewRoomDaoDao().PlaceRoomDevicesUpdate(param).Err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, true)(OK)
}

// HandleGetDeviceRoomList 设备房间列表
func HandleGetDeviceRoomList(ctx *gin.Context) {
	param := &request.GetDeviceRoomListReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	data := dao.NewRoomDaoDao().GetPlaceRoomDevicesList(param)
	if data.Err != nil {
		Response(ctx)("", CodeInternalServerError, false)(OK)
		return
	}

	Response(ctx)("", CodeSuccess, data.Unwrap())(OK)
}

// HandleBindDevice 绑定密码线充设备
func HandleBindDevice(ctx *gin.Context) {
	param := &struct {
		PreSn         string `json:"preSn" binding:"required"` // 批号
		BeginSn       int    `json:"beginSn" binding:"required,gt=0"`
		EndSn         int    `json:"endSn" binding:"required,gt=0"`
		PlaceId       int    `json:"placeId" binding:"required,gt=0"`
		PlaceName     string `json:"placeName"`
		DeviceTypeId  int    `json:"deviceTypeId"`
		DeviceModelId string `json:"deviceModelId"`
		SharedMode    string `json:"sharedMode"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()

	placeInfo := dao.NewPlaceDao().GetPlaceById(param.PlaceId).Unwrap().(*placemodel.PlaceModel)
	param.PlaceName = placeInfo.PlaceName
	// 获取设备类型 deviceTypeId
	deviceTypeId := dao.NewDeviceDao().GetDeviceBySnAndPreSn(param.PreSn, param.BeginSn).Unwrap().(*devices.DeviceModel).DeviceTypeId
	param.DeviceTypeId = deviceTypeId

	var count int64
	var strs []string
	status := 1

	//查询设备编号
	deviceSnIntervalMap := make(map[int]string)
	deviceCountModel := dao.NewDeviceDao().GetDeviceBySnInterval(param.BeginSn, param.EndSn, param.PreSn).Unwrap().([]devices.DeviceBySnIntervalModel)
	//设备总数封装map
	for _, v := range deviceCountModel {
		deviceSnIntervalMap[v.Sn] = v.DeviceSn
	}

	//查询设备是否已绑定
	deviceIsBingMap := make(map[int]int64)
	deviceIsBingModel := dao.NewDeviceDao().GetDeviceIsBing(param.BeginSn, param.EndSn, param.PreSn).Unwrap().([]devices.DeviceIsBingModel)

	for _, v := range deviceIsBingModel {
		deviceIsBingMap[v.Sn] = v.Total
	}

	for i := param.BeginSn; i <= param.EndSn; i++ {
		//deviceSn := utils.Join(param.PreSn, fmt.Sprintf("%0*d", 5, i))
		//log.Println("开始sn: ",i)
		//deviceSn := dao.NewDeviceDao().GetDeviceBySnAndPreSn(param.PreSn, i).Unwrap().(*devices.DeviceModel).DeviceSn
		deviceSn := deviceSnIntervalMap[i]
		m := devices.New()
		m.DeviceSn = deviceSn
		m.PlaceId = param.PlaceId
		m.PlaceName = param.PlaceName // 冗余字段 商户名称
		m.State = 2
		m.UpdateAt = dingo.Time(time.Now().Unix())
		m.DeployAt = dingo.Time(time.Now().Unix())

		// 判断设备是否已添加
		//devCount := dao.NewDeviceDao().GetDeviceUsedByPreSn(param.PreSn, i).Unwrap().(int64)
		if deviceIsBingMap[i] <= 0 {
			ok := dao.NewDeviceDao().UpdateDeviceBySn(m).Unwrap().(bool)
			if ok {
				count++
			} else {
				status = 0
				strs = append(strs, deviceSn)
			}
		}
	}

	pList := dao.NewPricesDao().GetPlacePriceByTypeId(param.PlaceId, param.DeviceTypeId, 5, 0, "").Unwrap().([]prices.PriceModel)
	ployList := dao.NewPloysDao().GetPloys(param.PlaceId, param.DeviceTypeId).Unwrap().([]devploys.DevicePloysModel)
	if count >= 1 && len(ployList) == 0 { // 自动关联设备的抽单策略
		// 新增商户奖励规则
		ployInfo := dao.NewPloysDao().GetDevicePloyInfo(param.DeviceTypeId).Unwrap().(*devploys.DevicePloysModel)
		ploy := ploys.New()
		ploy.Type = ployInfo.Type
		ploy.TypeId = ployInfo.TypeId
		ploy.Status = ployInfo.Status
		ploy.SharedMode = ployInfo.SharedMode
		ploy.PloyType = ployInfo.PloyType
		ploy.PloyName = ployInfo.PloyName
		ploy.Num = ployInfo.Num
		ploy.Range = ployInfo.Range
		ploy.PlaceId = param.PlaceId
		ploy.PlaceName = param.PlaceName
		ploy.CreateAt = dingo.Time(time.Now().Unix())
		ploy.UpdateAt = dingo.Time(time.Now().Unix())
		dao.NewPloysDao().InsertPlacePloys(ploy).Unwrap()
	}

	if count >= 1 && len(pList) == 0 { // 自动关联设备的计费规则
		//deviceSn := utils.Join(param.PreSn, fmt.Sprintf("%0*d", 5, param.BeginSn))
		deviceSn := dao.NewDeviceDao().GetDeviceBySnAndPreSn(param.PreSn, param.BeginSn).Unwrap().(*devices.DeviceModel).DeviceSn
		deviceInfo := dao.NewDeviceDao().FetchDeviceInfoWithType(deviceSn).Unwrap().(*devices.DeviceType) // 取第一条的设备信息

		// 新增商户计费规则 - 免押密码线(单套餐)
		if deviceInfo.SharedMode == "pcl" && deviceInfo.DeviceModelId == "XC-PCL-5-002" {
			// 获取设备类型 deviceTypeId
			//deviceTypeId := dao.NewDeviceDao().GetDeviceTypeIdByPreSn(param.PreSn).Unwrap().(int)
			ruleInfos := dao.NewPricesDao().GetDeviceRuleInfo(deviceTypeId, 1).Unwrap().([]devrule.DeviceRulesModel)
			ruleInfo := ruleInfos[0]
			m := prices.New()
			m.DeviceTypeId = deviceTypeId
			m.PlaceId = param.PlaceId
			m.Status = 1
			m.ProductId = utils.Str2Md5(helper.GenerateUUID())
			m.MaxPayPrice = ruleInfo.MaxPayPrice           // 日封顶价格
			m.PayIntervalPrice = ruleInfo.PayIntervalPrice // 每60分钟支付2元
			m.PayInterval = int(ruleInfo.PayInterval)      // 每60分钟支付2元
			m.MaxTime = ruleInfo.MaxTime                   // 最大使用时长
			m.BasePrice = ruleInfo.BasePrice               // 最低使用价格
			m.BaseTimes = int(ruleInfo.BaseTimes)          // 最低使用时长
			m.FreeTimes = int(ruleInfo.FreeTimes)          // 免费使用时长
			m.Deposit = ruleInfo.Deposit                   //  押金
			m.CreateAt = dingo.Time(time.Now().Unix())
			dao.NewPricesDao().InsertPlacePrice(m).Unwrap() // 新增 商户价格
		}
		// 新增商户计费规则 - 套餐密码线
		if deviceInfo.SharedMode == "pcl" && deviceInfo.DeviceModelId == "XC-PCL-5-001" {
			//deviceTypeId := dao.NewDeviceDao().GetDeviceTypeIdByPreSn(param.PreSn).Unwrap().(int)
			ruleInfos := dao.NewPricesDao().GetDeviceRuleInfo(deviceTypeId, 5).Unwrap().([]devrule.DeviceRulesModel)
			for _, ruleInfo := range ruleInfos {
				m := prices.New()
				m.DeviceTypeId = deviceTypeId
				m.PlaceId = param.PlaceId
				m.Status = ruleInfo.Status
				m.ProductId = utils.Str2Md5(helper.GenerateUUID())
				m.UseDuration = ruleInfo.UseDuration // 使用时长
				m.PayMoney = ruleInfo.PayMoney       // 支付金额-单位分
				m.SetMealNum = ruleInfo.SetMealNum   // 规则序号
				m.RuleName = ruleInfo.RuleName       // 规则名
				m.IsRecommend = ruleInfo.IsRecommend // 是否推荐
				m.Priority = ruleInfo.Priority       // 排序
				m.CreateAt = dingo.Time(time.Now().Unix())
				dao.NewPricesDao().InsertPlacePrice(m).Unwrap() // 新增 商户价格
			}
		}
	}
	// 绑定成功后更新该商户的设备条数 - 包含所有设备类型
	total := dao.NewDeviceDao().GetDeviceCountByPlaceId(param.PlaceId).Unwrap().(int64)
	dao.NewPlaceDao().UpdatePlaceCount(param.PlaceId, total)
	Response(ctx)(fmt.Sprintf("成功绑定%d条", count), CodeSuccess, &struct {
		Count  int64    `json:"count"`
		Strs   []string `json:"strs"`
		Status int      `json:"status"`
	}{
		Count:  count,
		Strs:   strs,
		Status: status,
	})(OK)
}

func insertPlacePloys(ployInfo *devploys.DevicePloysModel, plaeId int, placeName string) {
	ploy := ploys.New()
	ploy.Type = ployInfo.Type
	ploy.TypeId = ployInfo.TypeId
	ploy.Status = ployInfo.Status
	ploy.SharedMode = ployInfo.SharedMode
	ploy.PloyType = ployInfo.PloyType
	ploy.PloyName = ployInfo.PloyName
	ploy.Num = ployInfo.Num
	ploy.Range = ployInfo.Range
	ploy.PlaceId = plaeId
	ploy.PlaceName = placeName
	ploy.CreateAt = dingo.Time(time.Now().Unix())
	ploy.UpdateAt = dingo.Time(time.Now().Unix())
	dao.NewPloysDao().InsertPlacePloys(ploy).Unwrap()
}

// 修改设备类型
func UpdateDeviceTypeById(ctx *gin.Context) {
	param := &struct {
		DeviceSn     string `json:"deviceSn"`
		Id           int    `json:"id"`
		DeviceTypeId int    `json:"deviceTypeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	Response(ctx)("", CodeSuccess, dao.NewDeviceDao().UpdateDeviceTypeById(param.Id, param.DeviceTypeId).Unwrap())(OK)
}

// 修改设备类型
func UpdateDeviceTypeByPlaceId(ctx *gin.Context) {
	param := &struct {
		PlaceId      int `json:"placeId"`
		DeviceTypeId int `json:"deviceTypeId"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	Response(ctx)("修改成功", CodeSuccess, dao.NewDeviceDao().UpdateDeviceTypeByPlaceId(param.PlaceId, param.DeviceTypeId).Unwrap())(OK)
}

func LogicTest(c *gin.Context) {

	//logic.NewTaskLogic().UpdateOrderStatistics("")
	//logic.NewTaskLogic().UpdatePlaceLevel() // 统计

	//logic.NewTaskLogic().UpdatePlaceEntry()
	//logic.NewTaskLogic().AutoCompleteMemberOrder() // 每30分钟监控使用超时订单
	logic.NewTaskLogic().AgentIncomeStatistics(2, "pcl")
}
